package trocabi.Socle;

import trocabi.view.WaitingFrame;
import trocabi.TROCABI;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

/**
 * Pattern Singleton
 * @author philippe
 */
public class DBManager {
    private static final Logger    logger = Logger.getLogger("trocabi.Socle.DBManager");
    private static       DBManager instance=null;
    private              Connection connection=null;
   
    private DBManager() { 
    }
 
    public boolean showConnectionDialog(String user, String password) {
        int result=0;
        
        Object[] ID_MDP = new Object[4];
        ID_MDP[0] = "Nom d'utilisateur";
        JTextField tfLogin = new JTextField();
        ID_MDP[1] = tfLogin;
        ID_MDP[2] = "Mot de passe";
        JPasswordField tfPassword = new JPasswordField();
        ID_MDP[3] = tfPassword;
        result = JOptionPane.showOptionDialog(null, ID_MDP, "Connexion", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, new ImageIcon(".\\Ressources\\Information.png"), null, null);
        if (result==JOptionPane.CANCEL_OPTION) return false;
        user = tfLogin.getText();
        tfPassword.selectAll();
        password = tfPassword.getSelectedText();
        return true;
    }
    
    private void connect(String user, String password) throws TechnicalException {
        try {
            Class.forName(trocabi.Parameters.DB_DRIVER);
            if (trocabi.Parameters.BD_SECURE) {
                connection = DriverManager.getConnection(trocabi.Parameters.DB_URL, user, Hashage.sha256(password));
            } else {
                connection = DriverManager.getConnection(trocabi.Parameters.DB_URL, user, trocabi.Parameters.DB_PASSWORD);
            }
        } catch (ClassNotFoundException e) {
            TROCABI.fenetreExterne(TROCABI.ERREUR, "Erreur de chargement du pilote JDBC.");
            throw new TechnicalException(e.getMessage(),e.getCause());
        } catch (SQLException e) {
            TROCABI.fenetreExterne(TROCABI.ERREUR, String.format("Erreur de connexion à la base de données %s\n",e.getMessage()));
            throw new TechnicalException(e.getMessage(),e.getCause());
        }
    }
    
    private void showWaitingDialog(final String user, final String password) {
        WaitingFrame waitForMySql = new WaitingFrame("Connexion à la base de données...");
        waitForMySql.setTask(new Runnable() {
            public void run() {
                try {
                    connect(user,password);
                } catch (TechnicalException ex) {
                    Logger.getLogger(TROCABI.class.getName()).log(Level.SEVERE, null, ex);
                    System.exit(1); // exit program
                }
            }
        });
        try {
            waitForMySql.start();
            waitForMySql.waitEnd();
        }
        catch(TechnicalException e) {
            Logger.getLogger(TROCABI.class.getName()).log(Level.SEVERE, null, e);
        }
    }
    
    public static synchronized Connection getConnection() throws TechnicalException {
        String user=null, password=null;
        
        if (instance == null) { // create singleton
            instance = new DBManager();
        }
        try {
            if (isClosed()) { // get new connection
                if (trocabi.Parameters.DB_USER == null || trocabi.Parameters.DB_PASSWORD == null) {
                    if (!instance.showConnectionDialog(user, password)) return null;   
                }
                else {
                    user=trocabi.Parameters.DB_USER;
                    password=trocabi.Parameters.DB_PASSWORD;
                }
                instance.showWaitingDialog(user,password);
                instance.connection.setAutoCommit(false); // TODO: valider cette option
            }
       
        } catch(SQLException e) {
             DBManager.close();
             throw new TechnicalException(e.getMessage(),e.getCause());
        }
        return instance.connection;
    }
   
    public static boolean isClosed() {
        try {
            if (instance.connection == null || instance.connection.isClosed()) return true;
        } catch (SQLException e) {
            logger.severe(String.format("%s %s",e.getLocalizedMessage(),e.getMessage()));
        }    
        return false;
    }
    
    public static void close() {
        if (instance == null) return;
        try {
            if (instance.connection!=null) instance.connection.close();
        }
        catch (SQLException e) {
            logger.severe(String.format("%s %s",e.getLocalizedMessage(),e.getMessage()));
        }
        instance.connection=null;
    }
    
    public static java.sql.Date dateToSqlDate(java.util.Date date) {
        if (date==null) return null;
        return new java.sql.Date(date.getTime());
    }
    
    public static java.util.Date sqlDateToDate(java.sql.Date date) {
        if (date==null) return null;
        return new java.util.Date(date.getTime());
    }
}
